<?php
namespace DRY\Module;

/**
 * DonReY Framework 2012 :: Variable filter / changer, used normally to check and filter to prevent any kind of wrong data injection
 *
 * @author Wavetrex <wavetrex@gmail.com>
 * @link http://www.donrey.net/Documentation/Structure/Modules/filter.html
 * @license [GPL v3] http://www.gnu.org/licenses/gpl-3.0.html
 * @version 1.0.dev
 * @package DonReY
 * @subpackage Module.Filter
 */
class Filter extends base
{

	public function factory_Filter_Set()
	{
		return new \DRY\Filter\Set();
	}
}

namespace DRY\Filter;

/**
 * DonReY Framework 2012 :: A collection of filters that can be applied to a variable or a collection of variables
 *
 * @author Wavetrex <wavetrex@gmail.com>
 * @link http://www.donrey.net/Documentation/Structure/Modules/filter.html
 * @license [GPL v3] http://www.gnu.org/licenses/gpl-3.0.html
 * @version 1.0.dev
 * @package DonReY
 * @subpackage Module.Filter
 */
class Set
{

	/**
	 * Registered filters which will be apply()'ed to a variable
	 * @var array
	 */
	protected $filters = array();

	/**
	 *
	 * Errors encountered
	 * @var unknown_type
	 */
	protected $errors = array();

	protected function record_Error($filter, $step)
	{
		$this-> errors[$step] = $filter;
	}

	/**
	 * Character conversion from international letters to english standard letters
	 * Original data from Fuel Framework (http://fuelphp.com), /core/config/ascii.php. Thanks !
	 * + Made slightly more compact by grouping and reordering
	 * + Also added greek letters
	 * This list could stand a LOT of improvement, these are only the most commonly used around the world (european, chirilic, greek)
	 * @var array[string]
	 */
	static protected $alpha_intl2english = array(
		'/À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ|Α/' => 'A', '/à|á|â|ã|ä|å|ǻ|ā|ă|ą|ǎ|ª|а|α/' => 'a',
		'/æ|ǽ/' => 'ae', '/Æ|Ǽ/' => 'AE',
		'/Б|Β/' => 'B', '/б|β/' => 'b',
		'/Ç|Ć|Ĉ|Ċ|Č|Ц/' => 'C', '/ç|ć|ĉ|ċ|č|ц/' => 'c',
		'/Ч|Χ/' => 'Ch', '/ч|χ/' => 'ch',
		'/Ð|Ď|Đ|Д|Δ/' => 'D', '/ð|ď|đ|д|δ/' => 'd',
		'/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě|Е|Ё|Э|Ε/' => 'E', '/è|é|ê|ë|ē|ĕ|ė|ę|ě|е|ё|э|ε/' => 'e',
		'/Ф/' => 'F', '/ƒ|ф/' => 'f',
		'/Ĝ|Ğ|Ġ|Ģ|Γ/' => 'G', '/ĝ|ğ|ġ|ģ|г|γ/' => 'g',
		'/Ĥ|Ħ|Х/' => 'H', '/ĥ|ħ|х/' => 'h',
		'/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|И|Η|Ι/' => 'I', '/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|и|η|ι/' => 'i',
		'/Ĳ/' => 'IJ', '/ĳ/' => 'ij',
		'/Ĵ|Й/' => 'J', '/ĵ|й/' => 'j',
		'/Ю/' => 'Ju', '/ю/' => 'ju',
		'/Я/' => 'Ja', '/я/' => 'ja',
		'/Ķ|К|Κ/' => 'K', '/ķ|к/' => 'k',
		'/Ĺ|Ļ|Ľ|Ŀ|Ł|Л|Λ/' => 'L', '/ĺ|ļ|ľ|ŀ|ł|л|λ/' => 'l',
		'/М|Μ/' => 'M', '/м|μ/' => 'm',
		'/Ñ|Ń|Ņ|Ň|Н|Ν/' => 'N', '/ñ|ń|ņ|ň|ŉ|н|ν/' => 'n',
		'/Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ|О|Ο|Ω/' => 'O', '/ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º|о|ω/' => 'o',
		'/œ/' => 'oe', '/Œ/' => 'OE',
		'/П|Π|Ρ/' => 'P', '/п|π/' => 'p',
		'/Φ/' => 'Ph', '/φ/' => 'ph',
		'/Ψ/' => 'Ps', '/ψ/' => 'ps',
		'/Ŕ|Ŗ|Ř|Р/' => 'R',	'/ŕ|ŗ|ř|р|ρ/' => 'r',
		'/Ś|Ŝ|Ş|Š|С|Σ/' => 'S', '/ś|ŝ|ş|š|ſ|с|σ|ς/' => 's', '/ß/'=> 'ss',
		'/Ш/' => 'Sh', '/ш/' => 'sh',
		'/Щ/' => 'Shch', '/щ/' => 'shch',
		'/Ţ|Ť|Ŧ|Т|Τ/' => 'T',	'/ţ|ť|ŧ|т|τ/' => 't',
		'/Θ/' => 'Th', '/θ/' => 'th',
		'/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ|У/' => 'U',	'/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ|у/' => 'u',
		'/В/' => 'V', '/в/' => 'v',
		'/Ŵ/' => 'W', '/ŵ/' => 'w',
		'/Ξ/' => 'X', '/ξ/' => 'x',
		'/Ý|Ÿ|Ŷ|Ы|Υ/' => 'Y', '/ý|ÿ|ŷ|ы|υ/' => 'y',
		'/Ź|Ż|Ž|З|ζ|Ζ/' => 'Z',	'/ź|ż|ž|з/' => 'z',
		'/Ж/' => 'Zh', '/ж/' => 'zh',
	);

	/**
	 * Applies the filter set on the variable
	 * @param mixed $var String or array of strings (will go through it recursively)
	 * @param bool $stop If true, when an error is encountered the apply will return "false" and stop checking filters, if false, all problems with the variable will be recorded in $errors
	 * @return bool True if filtering was successful, False if it was stopped by an error
	 */
	public function apply(&$var, $stop = true, $clean_errors = true)
	{
		if($clean_errors)
			$this-> errors = array();

		if(is_string($var)) {
			foreach($this-> filters as $step=>$filter) {
				switch($filter[0]) {
					case 'c_IsNumeric';
						if(is_numeric($var)===false) {
							$this-> record_Error($filter[0], $step);
							if($stop) break 2;
						}
						break;

					case 'r_Default':
						if(empty($var))
							$var = $filter[1];
						break;
				}
			}

		} elseif (is_array($var) || is_object($var)) {
			// for multiple entries, if ANY of them encounter a problem, the entire set will return the error
			foreach($var as &$entry)
				$this-> apply($entry, $stop, false);
		}

		return !count($this-> errors);
	}

	/**
	 * Returns the errors that the last variable apply() has been encountered
	 * @param bool $clean True = clean error list
	 */
	public function get_Errors($clean = true)
	{
		$err = $this-> errors;
		if($clean)
			$this-> errors = array();
		return $err;
	}

	/**
	 * Condition - The variable must have minimum length of $minlen.
	 * (for strings it's simple, for numbers it's the quantity of figures in the number)
	 * @param int $minlen
	 */
	public function c_MinLength($minlen)
	{

	}

	/**
	 * Condition - The variable must be shorter than $maxlen characters
	 * (for strings it's simple, for numbers it's the quantity of figures in the number)
	 * @param int $minlen
	 */
	public function c_MaxLength($maxlen)
	{

	}

	/**
	 * Content of the variable must be a number
	 */
	public function c_IsNumeric()
	{
		$this-> filters[] = array(
			'c_IsNumeric'
		);
	}

	/**
	 * Content of the variable must be a valid date (recognized by strtotime(), date_parse() )
	 */
	public function c_IsDate()
	{
		$this-> filters[] = array(
			'c_IsDate'
		);
	}

	/**
	 * Replacer - Default. When the variable is empty(), this content is placed insted
	 */
	public function r_Default($default)
	{
		$this-> filters[] = array(
			'r_Default',
			$default
		);
	}

	/**
	 * Calls one of string->string function from PHP (like nl2br, substr, addslashes etc.)
	 * @param string $function_name
	 * @param (extra) Parameters to send to that function ( default - no parameters )
	 */
	public function r_PHPStr2Str($function_name)
	{
		$params = func_get_args();
		$function_name = array_shift($params);

		// Note: Some need extra parmeters to function properly, however this method provides the most commonly used defaults in case they are missing
		$allowed_functions = array(
			'addcslashes', 'addslashes', 'bin2hex', 'chunk_split', 'convert_uudecode', 'convert_uuencode', 'crypt',
			'hex2bin', 'html_entity_decode', 'htmlentities', 'htmlspecialchars_decode', 'htmlspecialchars', 'lcfirst',
			'ltrim', 'md5', 'metaphone', 'nl2br', 'quoted_printable_decode', 'quoted_printable_encode', 'quotemeta',
			'rtrim', 'sha1', 'soundex', 'str_pad', 'str_repeat', 'str_rot13', 'str_shuffle', 'strip_tags', 'stripcslashes',
			'stripslashes', 'strrev', 'strtolower', 'strtoupper', 'trim', 'ucfirst', 'ucwords', 'wordwrap'
		);

		if(!in_array($function_name, $allowed_functions))
			return false;

		switch($function_name) {
			case 'addcslashes':
				if(!isset($params[0]))
					$params[0] = "\0..\37!@\177..\377";
				break;
			case 'str_repeat':
				if(!isset($params[0]))
					$params[0] = 2;
				break;
			case 'str_repeat':
				if(!isset($params[0]))
					$params[0] = 2;
				break;
		}

		$this-> filters[] = array(
			'r_PHPStr2Str',
			$params
		);
	}

	/**
	 * Replacer - Filters out any kind of HTML from the variable content, by converting characters.
	 * @param bool $strip_mode True = Alternatively, it strips HTML tags instead of converting them into visibile <a> <b> </code> ... etc.
	 */
	public function r_NoHTML($strip_mode = false, $allowed = null)
	{

	}

	/**
	 * Replacer - Removes any kind of non-alphanumeric characters from the content, and replaces them with $replace
	 * @param bool $compress_replace If true (default), it compresses the resulting consecutive $replace characters into only one, and also trims that at the beginning and end of content.
	 */
	public function r_AlphaNum($compress_replace = true, $replace = ' ')
	{

	}

	/**
	 * Replacer - Converts many types of UTF characters like é or Ő etc. into their english equivalents ( e, o ), of course, losing special pronunciacion.
	 * This is useful for database searches, when the user doesn't know the exact foreign language spelling of non-english words,
	 *   or to generate url-compatible strings out of foreign language texts, in combination with the r_AlphaNum(true)
	 * @param bool $remove_unknown If true, removes unrecognised charactes instead of replacing them with $replace_with
	 */
	public function r_NoUTF($remove_unknown = false, $replace = ' ')
	{
	}
}